package com.example.mod.autoconfiguration;

import com.example.mod.api.annotation.ModInject;
import com.example.mod.api.annotation.ModService;
import com.example.mod.distribute.annotation.DistributeModInjectBeanProcessor;
import com.example.mod.distribute.annotation.DistributeModServiceBeanProcessor;
import com.example.mod.monolith.annotation.MonolithModInjectProcessor;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import java.util.concurrent.TimeUnit;

import static org.springframework.data.redis.cache.RedisCacheConfiguration.defaultCacheConfig;

/**
 * @author wangyongxu
 */
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(value = {ModService.class, ModInject.class})
public class ModAutoConfiguration {


    @ConditionalOnClass(DistributeModServiceBeanProcessor.class)
    @Configuration(proxyBeanMethods = false)
    static class Distribute {
        @Bean
        public DistributeModServiceBeanProcessor distributeModServiceBeanProcessor() {
            return new DistributeModServiceBeanProcessor();
        }

        @Bean
        public DistributeModInjectBeanProcessor distributeModInjectProcessor() {
            return new DistributeModInjectBeanProcessor();
        }

        @Bean
        public CacheManager cacheManager(RedisConnectionFactory factory) {
            RedisCacheConfiguration cacheConfiguration =
                    defaultCacheConfig()
                            .disableCachingNullValues()
                            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
            return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration).build();
        }

    }

    @ConditionalOnClass(MonolithModInjectProcessor.class)
    @Configuration(proxyBeanMethods = false)
    static class Monolith {
        @Bean
        public MonolithModInjectProcessor monolithModInjectProcessor() {
            return new MonolithModInjectProcessor();
        }

        @Bean
        public CacheManager cacheManagerWithCacheLoading(){
//            logger.info("cacheManagerWithCacheLoading" );
            Caffeine caffeine = Caffeine.newBuilder()
                    .initialCapacity(100)
                    .maximumSize(1000)
//                .refreshAfterWrite(5,TimeUnit.SECONDS)
                    .expireAfterWrite(50, TimeUnit.SECONDS);

            CaffeineCacheManager cacheManager = new CaffeineCacheManager();
            cacheManager.setAllowNullValues(true);
            cacheManager.setCaffeine(caffeine);
//        cacheManager.setCacheLoader(cacheLoader);
//            cacheManager.
//            cacheManager.setCacheNames(getNames());
            return cacheManager;
        }
    }

}